home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / flex / part05 < prev    next >
Encoding:
Internet Message Format  |  1988-05-02  |  41.4 KB

  1. Subject:  v14i083:  Flex, a lex replacement, Part05/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Vern Paxson <vern@lbl-csam.arpa>
  7. Posting-number: Volume 14, Issue 83
  8. Archive-name: flex/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 5)."
  17. # Contents:  tblcmp.c
  18. # Wrapped by rsalz@fig.bbn.com on Tue May  3 17:31:35 1988
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'tblcmp.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'tblcmp.c'\"
  22. else
  23. echo shar: Extracting \"'tblcmp.c'\" \(39351 characters\)
  24. sed "s/^X//" >'tblcmp.c' <<'END_OF_FILE'
  25. X/* tblcmp - table compression routines */
  26. X
  27. X/*
  28. X * Copyright (c) 1987, the University of California
  29. X * 
  30. X * The United States Government has rights in this work pursuant to
  31. X * contract no. DE-AC03-76SF00098 between the United States Department of
  32. X * Energy and the University of California.
  33. X * 
  34. X * This program may be redistributed.  Enhancements and derivative works
  35. X * may be created provided the new works, if made available to the general
  36. X * public, are made available for use by anyone.
  37. X */
  38. X
  39. X#include "flexdef.h"
  40. X
  41. X/* bldtbl - build table entries for dfa state
  42. X *
  43. X * synopsis
  44. X *   int state[numecs], statenum, totaltrans, comstate, comfreq;
  45. X *   bldtbl( state, statenum, totaltrans, comstate, comfreq );
  46. X *
  47. X * State is the statenum'th dfa state.  It is indexed by equivalence class and
  48. X * gives the number of the state to enter for a given equivalence class.
  49. X * totaltrans is the total number of transitions out of the state.  Comstate
  50. X * is that state which is the destination of the most transitions out of State.
  51. X * Comfreq is how many transitions there are out of State to Comstate.
  52. X *
  53. X * A note on terminology:
  54. X *    "protos" are transition tables which have a high probability of
  55. X * either being redundant (a state processed later will have an identical
  56. X * transition table) or nearly redundant (a state processed later will have
  57. X * many of the same out-transitions).  A "most recently used" queue of
  58. X * protos is kept around with the hope that most states will find a proto
  59. X * which is similar enough to be usable, and therefore compacting the
  60. X * output tables.
  61. X *    "templates" are a special type of proto.  If a transition table is
  62. X * homogeneous or nearly homogeneous (all transitions go to the same
  63. X * destination) then the odds are good that future states will also go
  64. X * to the same destination state on basically the same character set.
  65. X * These homogeneous states are so common when dealing with large rule
  66. X * sets that they merit special attention.  If the transition table were
  67. X * simply made into a proto, then (typically) each subsequent, similar
  68. X * state will differ from the proto for two out-transitions.  One of these
  69. X * out-transitions will be that character on which the proto does not go
  70. X * to the common destination, and one will be that character on which the
  71. X * state does not go to the common destination.  Templates, on the other
  72. X * hand, go to the common state on EVERY transition character, and therefore
  73. X * cost only one difference.
  74. X */
  75. X
  76. bldtbl( state, statenum, totaltrans, comstate, comfreq )
  77. int state[], statenum, totaltrans, comstate, comfreq;
  78. X
  79. X    {
  80. X    int extptr, extrct[2][CSIZE + 1];
  81. X    int mindiff, minprot, i, d;
  82. X    int checkcom;
  83. X
  84. X    /* If extptr is 0 then the first array of extrct holds the result of the
  85. X     * "best difference" to date, which is those transitions which occur in
  86. X     * "state" but not in the proto which, to date, has the fewest differences
  87. X     * between itself and "state".  If extptr is 1 then the second array of
  88. X     * extrct hold the best difference.  The two arrays are toggled
  89. X     * between so that the best difference to date can be kept around and
  90. X     * also a difference just created by checking against a candidate "best"
  91. X     * proto.
  92. X     */
  93. X
  94. X    extptr = 0;
  95. X
  96. X    /* if the state has too few out-transitions, don't bother trying to
  97. X     * compact its tables
  98. X     */
  99. X
  100. X    if ( (totaltrans * 100) < (numecs * PROTO_SIZE_PERCENTAGE) )
  101. X    mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
  102. X
  103. X    else
  104. X    {
  105. X    /* checkcom is true if we should only check "state" against
  106. X     * protos which have the same "comstate" value
  107. X     */
  108. X
  109. X    checkcom = comfreq * 100 > totaltrans * CHECK_COM_PERCENTAGE;
  110. X
  111. X    minprot = firstprot;
  112. X    mindiff = totaltrans;
  113. X
  114. X    if ( checkcom )
  115. X        {
  116. X        /* find first proto which has the same "comstate" */
  117. X        for ( i = firstprot; i != NIL; i = protnext[i] )
  118. X        if ( protcomst[i] == comstate )
  119. X            {
  120. X            minprot = i;
  121. X            mindiff = tbldiff( state, minprot, extrct[extptr] );
  122. X            break;
  123. X            }
  124. X        }
  125. X
  126. X    else
  127. X        {
  128. X        /* since we've decided that the most common destination out
  129. X         * of "state" does not occur with a high enough frequency,
  130. X         * we set the "comstate" to zero, assuring that if this state
  131. X         * is entered into the proto list, it will not be considered
  132. X         * a template.
  133. X         */
  134. X        comstate = 0;
  135. X
  136. X        if ( firstprot != NIL )
  137. X        {
  138. X        minprot = firstprot;
  139. X        mindiff = tbldiff( state, minprot, extrct[extptr] );
  140. X        }
  141. X        }
  142. X
  143. X    /* we now have the first interesting proto in "minprot".  If
  144. X     * it matches within the tolerances set for the first proto,
  145. X     * we don't want to bother scanning the rest of the proto list
  146. X     * to see if we have any other reasonable matches.
  147. X     */
  148. X
  149. X    if ( mindiff * 100 > totaltrans * FIRST_MATCH_DIFF_PERCENTAGE )
  150. X        { /* not a good enough match.  Scan the rest of the protos */
  151. X        for ( i = minprot; i != NIL; i = protnext[i] )
  152. X        {
  153. X        d = tbldiff( state, i, extrct[1 - extptr] );
  154. X        if ( d < mindiff )
  155. X            {
  156. X            extptr = 1 - extptr;
  157. X            mindiff = d;
  158. X            minprot = i;
  159. X            }
  160. X        }
  161. X        }
  162. X
  163. X    /* check if the proto we've decided on as our best bet is close
  164. X     * enough to the state we want to match to be usable
  165. X     */
  166. X
  167. X    if ( mindiff * 100 > totaltrans * ACCEPTABLE_DIFF_PERCENTAGE )
  168. X        {
  169. X        /* no good.  If the state is homogeneous enough, we make a
  170. X         * template out of it.  Otherwise, we make a proto.
  171. X         */
  172. X
  173. X        if ( comfreq * 100 >= totaltrans * TEMPLATE_SAME_PERCENTAGE )
  174. X        mktemplate( state, statenum, comstate );
  175. X
  176. X        else
  177. X        {
  178. X        mkprot( state, statenum, comstate );
  179. X        mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
  180. X        }
  181. X        }
  182. X
  183. X    else
  184. X        { /* use the proto */
  185. X        mkentry( extrct[extptr], numecs, statenum,
  186. X             prottbl[minprot], mindiff );
  187. X
  188. X        /* if this state was sufficiently different from the proto
  189. X         * we built it from, make it, too, a proto
  190. X         */
  191. X
  192. X        if ( mindiff * 100 >= totaltrans * NEW_PROTO_DIFF_PERCENTAGE )
  193. X        mkprot( state, statenum, comstate );
  194. X
  195. X        /* since mkprot added a new proto to the proto queue, it's possible
  196. X         * that "minprot" is no longer on the proto queue (if it happened
  197. X         * to have been the last entry, it would have been bumped off).
  198. X         * If it's not there, then the new proto took its physical place
  199. X         * (though logically the new proto is at the beginning of the
  200. X         * queue), so in that case the following call will do nothing.
  201. X         */
  202. X
  203. X        mv2front( minprot );
  204. X        }
  205. X    }
  206. X    }
  207. X
  208. X
  209. X/* cmptmps - compress template table entries
  210. X *
  211. X * synopsis
  212. X *    cmptmps();
  213. X *
  214. X *  template tables are compressed by using the 'template equivalence
  215. X *  classes', which are collections of transition character equivalence
  216. X *  classes which always appear together in templates - really meta-equivalence
  217. X *  classes.  until this point, the tables for templates have been stored
  218. X *  up at the top end of the nxt array; they will now be compressed and have
  219. X *  table entries made for them.
  220. X */
  221. X
  222. cmptmps()
  223. X
  224. X    {
  225. X    int tmpstorage[CSIZE + 1];
  226. X    register int *tmp = tmpstorage, i, j;
  227. X    int totaltrans, trans;
  228. X
  229. X    peakpairs = numtemps * numecs + tblend;
  230. X
  231. X    if ( usemecs )
  232. X    {
  233. X    /* create equivalence classes base on data gathered on template
  234. X     * transitions
  235. X     */
  236. X
  237. X    nummecs = cre8ecs( tecfwd, tecbck, numecs );
  238. X    }
  239. X    
  240. X    else
  241. X    nummecs = numecs;
  242. X
  243. X    if ( lastdfa + numtemps + 1 >= current_max_dfas )
  244. X    increase_max_dfas();
  245. X
  246. X    /* loop through each template */
  247. X
  248. X    for ( i = 1; i <= numtemps; ++i )
  249. X    {
  250. X    totaltrans = 0;    /* number of non-jam transitions out of this template */
  251. X
  252. X    for ( j = 1; j <= numecs; ++j )
  253. X        {
  254. X        trans = tnxt[numecs * i + j];
  255. X
  256. X        if ( usemecs )
  257. X        {
  258. X        /* the absolute value of tecbck is the meta-equivalence class
  259. X         * of a given equivalence class, as set up by cre8ecs
  260. X         */
  261. X        if ( tecbck[j] > 0 )
  262. X            {
  263. X            tmp[tecbck[j]] = trans;
  264. X
  265. X            if ( trans > 0 )
  266. X            ++totaltrans;
  267. X            }
  268. X        }
  269. X
  270. X        else
  271. X        {
  272. X        tmp[j] = trans;
  273. X
  274. X        if ( trans > 0 )
  275. X            ++totaltrans;
  276. X        }
  277. X        }
  278. X
  279. X    /* it is assumed (in a rather subtle way) in the skeleton that
  280. X     * if we're using meta-equivalence classes, the def[] entry for
  281. X     * all templates is the jam template, i.e., templates never default
  282. X     * to other non-jam table entries (e.g., another template)
  283. X     */
  284. X
  285. X    /* leave room for the jam-state after the last real state */
  286. X    mkentry( tmp, nummecs, lastdfa + i + 1, JAMSTATE, totaltrans );
  287. X    }
  288. X    }
  289. X
  290. X
  291. X
  292. X/* expand_nxt_chk - expand the next check arrays */
  293. X
  294. expand_nxt_chk()
  295. X
  296. X    {
  297. X    register int old_max = current_max_xpairs;
  298. X
  299. X    current_max_xpairs += MAX_XPAIRS_INCREMENT;
  300. X
  301. X    ++num_reallocs;
  302. X
  303. X    nxt = reallocate_integer_array( nxt, current_max_xpairs );
  304. X    chk = reallocate_integer_array( chk, current_max_xpairs );
  305. X
  306. X    bzero( (char *) (chk + old_max),
  307. X       MAX_XPAIRS_INCREMENT * sizeof( int ) / sizeof( char ) );
  308. X    }
  309. X
  310. X
  311. X/* find_table_space - finds a space in the table for a state to be placed
  312. X *
  313. X * synopsis
  314. X *     int *state, numtrans, block_start;
  315. X *     int find_table_space();
  316. X *
  317. X *     block_start = find_table_space( state, numtrans );
  318. X *
  319. X * State is the state to be added to the full speed transition table.
  320. X * Numtrans is the number of out-transitions for the state.
  321. X *
  322. X * find_table_space() returns the position of the start of the first block (in
  323. X * chk) able to accommodate the state
  324. X *
  325. X * In determining if a state will or will not fit, find_table_space() must take
  326. X * into account the fact that an end-of-buffer state will be added at [0],
  327. X * and an action number will be added in [-1].
  328. X */
  329. X
  330. int find_table_space( state, numtrans )
  331. int *state, numtrans;
  332. X    
  333. X    {
  334. X    /* firstfree is the position of the first possible occurrence of two
  335. X     * consecutive unused records in the chk and nxt arrays
  336. X     */
  337. X    register int i;
  338. X    register int *state_ptr, *chk_ptr;
  339. X    register int *ptr_to_last_entry_in_state;
  340. X
  341. X    /* if there are too many out-transitions, put the state at the end of
  342. X     * nxt and chk
  343. X     */
  344. X    if ( numtrans > MAX_XTIONS_FOR_FULL_INTERIOR_FIT )
  345. X    {
  346. X    /* if table is empty, return the first available spot in chk/nxt,
  347. X     * which should be 1
  348. X     */
  349. X    if ( tblend < 2 )
  350. X        return ( 1 );
  351. X
  352. X    i = tblend - numecs;    /* start searching for table space near the
  353. X                 * end of chk/nxt arrays
  354. X                 */
  355. X    }
  356. X
  357. X    else
  358. X    i = firstfree;        /* start searching for table space from the
  359. X                 * beginning (skipping only the elements
  360. X                 * which will definitely not hold the new
  361. X                 * state)
  362. X                 */
  363. X
  364. X    while ( 1 )        /* loops until a space is found */
  365. X    {
  366. X    if ( i + numecs > current_max_xpairs )
  367. X        expand_nxt_chk();
  368. X
  369. X    /* loops until space for end-of-buffer and action number are found */
  370. X    while ( 1 )
  371. X        {
  372. X        if ( chk[i - 1] == 0 )    /* check for action number space */
  373. X        {
  374. X        if ( chk[i] == 0 )    /* check for end-of-buffer space */
  375. X            break;
  376. X
  377. X        else
  378. X            i += 2;    /* since i != 0, there is no use checking to
  379. X                 * see if (++i) - 1 == 0, because that's the
  380. X                 * same as i == 0, so we skip a space
  381. X                 */
  382. X        }
  383. X
  384. X        else
  385. X        ++i;
  386. X
  387. X        if ( i + numecs > current_max_xpairs )
  388. X        expand_nxt_chk();
  389. X        }
  390. X
  391. X    /* if we started search from the beginning, store the new firstfree for
  392. X     * the next call of find_table_space()
  393. X     */
  394. X    if ( numtrans <= MAX_XTIONS_FOR_FULL_INTERIOR_FIT )
  395. X        firstfree = i + 1;
  396. X
  397. X    /* check to see if all elements in chk (and therefore nxt) that are
  398. X     * needed for the new state have not yet been taken
  399. X     */
  400. X
  401. X    state_ptr = &state[1];
  402. X    ptr_to_last_entry_in_state = &chk[i + numecs + 1];
  403. X
  404. X    for ( chk_ptr = &chk[i + 1]; chk_ptr != ptr_to_last_entry_in_state;
  405. X          ++chk_ptr )
  406. X        if ( *(state_ptr++) != 0 && *chk_ptr != 0 )
  407. X        break;
  408. X
  409. X    if ( chk_ptr == ptr_to_last_entry_in_state )
  410. X        return ( i );
  411. X
  412. X    else
  413. X        ++i;
  414. X    }
  415. X    }
  416. X
  417. X
  418. X/* genctbl - generates full speed compressed transition table
  419. X *
  420. X * synopsis
  421. X *     genctbl();
  422. X */
  423. X
  424. genctbl()
  425. X
  426. X    {
  427. X    register int i;
  428. X
  429. X    /* table of verify for transition and offset to next state */
  430. X    printf( "static struct yy_trans_info yy_transition[%d] =\n",
  431. X        tblend + numecs + 1 );
  432. X    printf( "    {\n" );
  433. X    
  434. X    /* We want the transition to be represented as the offset to the
  435. X     * next state, not the actual state number, which is what it currently is.
  436. X     * The offset is base[nxt[i]] - base[chk[i]].  That's just the
  437. X     * difference between the starting points of the two involved states
  438. X     * (to - from).
  439. X     *
  440. X     * first, though, we need to find some way to put in our end-of-buffer
  441. X     * flags and states.  We do this by making a state with absolutely no
  442. X     * transitions.  We put it at the end of the table.
  443. X     */
  444. X    /* at this point, we're guaranteed that there's enough room in nxt[]
  445. X     * and chk[] to hold tblend + numecs entries.  We need just two slots.
  446. X     * One for the action and one for the end-of-buffer transition.  We
  447. X     * now *assume* that we're guaranteed the only character we'll try to
  448. X     * index this nxt/chk pair with is EOB, i.e., 0, so we don't have to
  449. X     * make sure there's room for jam entries for other characters.
  450. X     */
  451. X
  452. X    base[lastdfa + 1] = tblend + 2;
  453. X    nxt[tblend + 1] = END_OF_BUFFER_ACTION;
  454. X    chk[tblend + 1] = numecs + 1;
  455. X    chk[tblend + 2] = 1; /* anything but EOB */
  456. X    nxt[tblend + 2] = 0; /* so that "make test" won't show arb. differences */
  457. X
  458. X    /* make sure every state has a end-of-buffer transition and an action # */
  459. X    for ( i = 0; i <= lastdfa; ++i )
  460. X    {
  461. X    chk[base[i]] = EOB_POSITION;
  462. X    chk[base[i] - 1] = ACTION_POSITION;
  463. X    nxt[base[i] - 1] = dfaacc[i].dfaacc_state;    /* action number */
  464. X    }
  465. X
  466. X    for ( i = 0; i <= lastsc * 2; ++i )
  467. X    nxt[base[i] - 1] = DEFAULT_ACTION;
  468. X
  469. X    dataline = 0;
  470. X    datapos = 0;
  471. X
  472. X    for ( i = 0; i <= tblend; ++i )
  473. X    {
  474. X    if ( chk[i] == EOB_POSITION )
  475. X        transition_struct_out( 0, base[lastdfa + 1] - i );
  476. X
  477. X    else if ( chk[i] == ACTION_POSITION )
  478. X        transition_struct_out( 0, nxt[i] );
  479. X
  480. X    else if ( chk[i] > numecs || chk[i] == 0 )
  481. X        transition_struct_out( 0, 0 );        /* unused slot */
  482. X
  483. X    else    /* verify, transition */
  484. X        transition_struct_out( chk[i], base[nxt[i]] - (i - chk[i]) );
  485. X    }
  486. X
  487. X
  488. X    /* here's the final, end-of-buffer state */
  489. X    transition_struct_out( chk[tblend + 1], nxt[tblend + 1] );
  490. X    transition_struct_out( chk[tblend + 2], nxt[tblend + 2] );
  491. X
  492. X    printf( "    };\n" );
  493. X    printf( "\n" );
  494. X
  495. X    /* table of pointers to start states */
  496. X    printf( "static struct yy_trans_info *yy_state_ptr[%d] =\n",
  497. X    lastsc * 2 + 1 );
  498. X    printf( "    {\n" );
  499. X
  500. X    for ( i = 0; i <= lastsc * 2; ++i )
  501. X    printf( "    &yy_transition[%d],\n", base[i] );
  502. X
  503. X    printf( "    };\n" );
  504. X
  505. X    if ( useecs )
  506. X    genecs();
  507. X    }
  508. X
  509. X
  510. X/* gentabs - generate data statements for the transition tables
  511. X *
  512. X * synopsis
  513. X *    gentabs();
  514. X */
  515. X
  516. gentabs()
  517. X
  518. X    {
  519. X    int i, j, k, *accset, nacc, *acc_array;
  520. X    char clower();
  521. X
  522. X    /* *everything* is done in terms of arrays starting at 1, so provide
  523. X     * a null entry for the zero element of all FTL arrays
  524. X     */
  525. X    static char ftl_long_decl[] = "static long int %c[%d] =\n    {   0,\n";
  526. X    static char ftl_short_decl[] = "static short int %c[%d] =\n    {   0,\n";
  527. X    static char ftl_char_decl[] = "static char %c[%d] =\n    {   0,\n";
  528. X
  529. X    acc_array = allocate_integer_array( current_max_dfas );
  530. X    nummt = 0;
  531. X
  532. X    if ( fulltbl )
  533. X    jambase = lastdfa + 1;    /* home of "jam" pseudo-state */
  534. X
  535. X    printf( "#define YY_JAM %d\n", jamstate );
  536. X    printf( "#define YY_JAM_BASE %d\n", jambase );
  537. X
  538. X    if ( usemecs )
  539. X    printf( "#define YY_TEMPLATE %d\n", lastdfa + 2 );
  540. X
  541. X    if ( reject )
  542. X    {
  543. X    /* write out accepting list and pointer list
  544. X     * first we generate the ACCEPT array.  In the process, we compute
  545. X     * the indices that will go into the ALIST array, and save the
  546. X     * indices in the dfaacc array
  547. X     */
  548. X
  549. X    printf( accnum > 127 ? ftl_short_decl : ftl_char_decl,
  550. X        ACCEPT, max( numas, 1 ) + 1 );
  551. X
  552. X    j = 1;    /* index into ACCEPT array */
  553. X
  554. X    for ( i = 1; i <= lastdfa; ++i )
  555. X        {
  556. X        acc_array[i] = j;
  557. X
  558. X        if ( accsiz[i] != 0 )
  559. X        {
  560. X        accset = dfaacc[i].dfaacc_set;
  561. X        nacc = accsiz[i];
  562. X
  563. X        if ( trace )
  564. X            fprintf( stderr, "state # %d accepts: ", i );
  565. X
  566. X        for ( k = 1; k <= nacc; ++k )
  567. X            {
  568. X            ++j;
  569. X            mkdata( accset[k] );
  570. X
  571. X            if ( trace )
  572. X            {
  573. X            fprintf( stderr, "[%d]", accset[k] );
  574. X
  575. X            if ( k < nacc )
  576. X                fputs( ", ", stderr );
  577. X            else
  578. X                putc( '\n', stderr );
  579. X            }
  580. X            }
  581. X        }
  582. X        }
  583. X
  584. X    /* add accepting number for the "jam" state */
  585. X    acc_array[i] = j;
  586. X
  587. X    dataend();
  588. X    }
  589. X    
  590. X    else
  591. X    {
  592. X    for ( i = 1; i <= lastdfa; ++i )
  593. X        acc_array[i] = dfaacc[i].dfaacc_state;
  594. X    
  595. X    acc_array[i] = 0; /* add (null) accepting number for jam state */
  596. X    }
  597. X
  598. X    /* spit out ALIST array.  If we're doing "reject", it'll be pointers
  599. X     * into the ACCEPT array.  Otherwise it's actual accepting numbers.
  600. X     * In either case, we just dump the numbers.
  601. X     */
  602. X
  603. X    /* "lastdfa + 2" is the size of ALIST; includes room for FTL arrays
  604. X     * beginning at 0 and for "jam" state
  605. X     */
  606. X    k = lastdfa + 2;
  607. X
  608. X    if ( reject )
  609. X    /* we put a "cap" on the table associating lists of accepting
  610. X     * numbers with state numbers.  This is needed because we tell
  611. X     * where the end of an accepting list is by looking at where
  612. X     * the list for the next state starts.
  613. X     */
  614. X    ++k;
  615. X
  616. X    printf( ((reject && numas > 126) || accnum > 127) ?
  617. X        ftl_short_decl : ftl_char_decl, ALIST, k );
  618. X
  619. X    /* set up default actions */
  620. X    for ( i = 1; i <= lastsc * 2; ++i )
  621. X    acc_array[i] = DEFAULT_ACTION;
  622. X
  623. X    acc_array[end_of_buffer_state] = END_OF_BUFFER_ACTION;
  624. X
  625. X    for ( i = 1; i <= lastdfa; ++i )
  626. X    {
  627. X    mkdata( acc_array[i] );
  628. X
  629. X    if ( ! reject && trace && acc_array[i] )
  630. X        fprintf( stderr, "state # %d accepts: [%d]\n", i, acc_array[i] );
  631. X    }
  632. X
  633. X    /* add entry for "jam" state */
  634. X    mkdata( acc_array[i] );
  635. X
  636. X    if ( reject )
  637. X    /* add "cap" for the list */
  638. X    mkdata( acc_array[i] );
  639. X
  640. X    dataend();
  641. X
  642. X    if ( useecs )
  643. X    genecs();
  644. X
  645. X    if ( usemecs )
  646. X    {
  647. X    /* write out meta-equivalence classes (used to index templates with) */
  648. X
  649. X    if ( trace )
  650. X        fputs( "\n\nMeta-Equivalence Classes:\n", stderr );
  651. X
  652. X    printf( ftl_char_decl, MATCHARRAY, numecs + 1 );
  653. X
  654. X    for ( i = 1; i <= numecs; ++i )
  655. X        {
  656. X        if ( trace )
  657. X        fprintf( stderr, "%d = %d\n", i, abs( tecbck[i] ) );
  658. X
  659. X        mkdata( abs( tecbck[i] ) );
  660. X        }
  661. X
  662. X    dataend();
  663. X    }
  664. X
  665. X    if ( ! fulltbl )
  666. X    {
  667. X    int total_states = lastdfa + numtemps;
  668. X
  669. X    printf( tblend > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
  670. X        BASEARRAY, total_states + 1 );
  671. X
  672. X    for ( i = 1; i <= lastdfa; ++i )
  673. X        {
  674. X        register int d = def[i];
  675. X
  676. X        if ( base[i] == JAMSTATE )
  677. X        base[i] = jambase;
  678. X
  679. X        if ( d == JAMSTATE )
  680. X        def[i] = jamstate;
  681. X
  682. X        else if ( d < 0 )
  683. X        {
  684. X        /* template reference */
  685. X        ++tmpuses;
  686. X        def[i] = lastdfa - d + 1;
  687. X        }
  688. X
  689. X        mkdata( base[i] );
  690. X        }
  691. X
  692. X    /* generate jam state's base index */
  693. X    mkdata( base[i] );
  694. X
  695. X    for ( ++i /* skip jam state */; i <= total_states; ++i )
  696. X        {
  697. X        mkdata( base[i] );
  698. X        def[i] = jamstate;
  699. X        }
  700. X
  701. X    dataend();
  702. X
  703. X    printf( tblend > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
  704. X        DEFARRAY, total_states + 1 );
  705. X
  706. X    for ( i = 1; i <= total_states; ++i )
  707. X        mkdata( def[i] );
  708. X
  709. X    dataend();
  710. X
  711. X    printf( lastdfa > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
  712. X        NEXTARRAY, tblend + 1 );
  713. X
  714. X    for ( i = 1; i <= tblend; ++i )
  715. X        {
  716. X        if ( nxt[i] == 0 || chk[i] == 0 )
  717. X        nxt[i] = jamstate;    /* new state is the JAM state */
  718. X
  719. X        mkdata( nxt[i] );
  720. X        }
  721. X
  722. X    dataend();
  723. X
  724. X    printf( lastdfa > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
  725. X        CHECKARRAY, tblend + 1 );
  726. X
  727. X    for ( i = 1; i <= tblend; ++i )
  728. X        {
  729. X        if ( chk[i] == 0 )
  730. X        ++nummt;
  731. X
  732. X        mkdata( chk[i] );
  733. X        }
  734. X
  735. X    dataend();
  736. X    }
  737. X    }
  738. X
  739. X
  740. X/* generate equivalence-class tables */
  741. X
  742. genecs()
  743. X
  744. X    {
  745. X    register int i, j;
  746. X    static char ftl_char_decl[] = "static char %c[%d] =\n    {   0,\n";
  747. X    int numrows;
  748. X
  749. X    printf( ftl_char_decl, ECARRAY, CSIZE + 1 );
  750. X
  751. X    for ( i = 1; i <= CSIZE; ++i )
  752. X    {
  753. X    if ( caseins && (i >= 'A') && (i <= 'Z') )
  754. X        ecgroup[i] = ecgroup[clower( i )];
  755. X
  756. X    ecgroup[i] = abs( ecgroup[i] );
  757. X    mkdata( ecgroup[i] );
  758. X    }
  759. X
  760. X    dataend();
  761. X
  762. X    if ( trace )
  763. X    {
  764. X    fputs( "\n\nEquivalence Classes:\n\n", stderr );
  765. X
  766. X    numrows = (CSIZE + 1) / 8;
  767. X
  768. X    for ( j = 1; j <= numrows; ++j )
  769. X        {
  770. X        for ( i = j; i <= CSIZE; i = i + numrows )
  771. X        {
  772. X        if ( i >= 1 && i <= 31 )
  773. X            fprintf( stderr, "^%c = %-2d",
  774. X                 'A' + i - 1, ecgroup[i] );
  775. X
  776. X        else if ( i >= 32 && i <= 126 )
  777. X            fprintf( stderr, " %c = %-2d", i, ecgroup[i] );
  778. X
  779. X        else if ( i == 127 )
  780. X            fprintf( stderr, "^@ = %-2d", ecgroup[i] );
  781. X
  782. X        else
  783. X            fprintf( stderr, "\nSomething Weird: %d = %d\n", i,
  784. X                 ecgroup[i] );
  785. X
  786. X        putc( '\t', stderr );
  787. X        }
  788. X
  789. X        putc( '\n', stderr );
  790. X        }
  791. X    }
  792. X    }
  793. X
  794. X
  795. X/* inittbl - initialize transition tables
  796. X *
  797. X * synopsis
  798. X *   inittbl();
  799. X *
  800. X * Initializes "firstfree" to be one beyond the end of the table.  Initializes
  801. X * all "chk" entries to be zero.  Note that templates are built in their
  802. X * own tbase/tdef tables.  They are shifted down to be contiguous
  803. X * with the non-template entries during table generation.
  804. X */
  805. inittbl()
  806. X
  807. X    {
  808. X    register int i;
  809. X
  810. X    bzero( (char *) chk, current_max_xpairs * sizeof( int ) / sizeof( char ) );
  811. X
  812. X    tblend = 0;
  813. X    firstfree = tblend + 1;
  814. X    numtemps = 0;
  815. X
  816. X    if ( usemecs )
  817. X    {
  818. X    /* set up doubly-linked meta-equivalence classes
  819. X     * these are sets of equivalence classes which all have identical
  820. X     * transitions out of TEMPLATES
  821. X     */
  822. X
  823. X    tecbck[1] = NIL;
  824. X
  825. X    for ( i = 2; i <= numecs; ++i )
  826. X        {
  827. X        tecbck[i] = i - 1;
  828. X        tecfwd[i - 1] = i;
  829. X        }
  830. X
  831. X    tecfwd[numecs] = NIL;
  832. X    }
  833. X    }
  834. X
  835. X
  836. X/* make_tables - generate transition tables
  837. X *
  838. X * synopsis
  839. X *     make_tables();
  840. X *
  841. X * Generates transition tables and finishes generating output file
  842. X */
  843. X
  844. make_tables()
  845. X
  846. X    {
  847. X    if ( fullspd )
  848. X    { /* need to define YY_TRANS_OFFSET_TYPE as a size large
  849. X       * enough to hold the biggest offset
  850. X       */
  851. X    int total_table_size = tblend + numecs + 1;
  852. X
  853. X    printf( "#define YY_TRANS_OFFSET_TYPE %s\n",
  854. X        total_table_size > MAX_SHORT ? "long" : "short" );
  855. X    }
  856. X    
  857. X    if ( fullspd || fulltbl )
  858. X    skelout();
  859. X
  860. X    /* compute the tables and copy them to output file */
  861. X    if ( fullspd )
  862. X    genctbl();
  863. X
  864. X    else
  865. X    gentabs();
  866. X
  867. X    skelout();
  868. X
  869. X    (void) fclose( temp_action_file );
  870. X    temp_action_file = fopen( action_file_name, "r" );
  871. X
  872. X    /* copy prolog from action_file to output file */
  873. X    action_out();
  874. X
  875. X    skelout();
  876. X
  877. X    /* copy actions from action_file to output file */
  878. X    action_out();
  879. X
  880. X    skelout();
  881. X
  882. X    /* copy remainder of input to output */
  883. X
  884. X    line_directive_out( stdout );
  885. X    (void) flexscan(); /* copy remainder of input to output */
  886. X    }
  887. X
  888. X
  889. X/* mkdeftbl - make the default, "jam" table entries
  890. X *
  891. X * synopsis
  892. X *   mkdeftbl();
  893. X */
  894. X
  895. mkdeftbl()
  896. X
  897. X    {
  898. X    int i;
  899. X
  900. X    jamstate = lastdfa + 1;
  901. X
  902. X    if ( tblend + numecs > current_max_xpairs )
  903. X    expand_nxt_chk();
  904. X
  905. X    for ( i = 1; i <= numecs; ++i )
  906. X    {
  907. X    nxt[tblend + i] = 0;
  908. X    chk[tblend + i] = jamstate;
  909. X    }
  910. X
  911. X    jambase = tblend;
  912. X
  913. X    base[jamstate] = jambase;
  914. X
  915. X    /* should generate a run-time array bounds check if
  916. X     * ever used as a default
  917. X     */
  918. X    def[jamstate] = BAD_SUBSCRIPT;
  919. X
  920. X    tblend += numecs;
  921. X    ++numtemps;
  922. X    }
  923. X
  924. X
  925. X/* mkentry - create base/def and nxt/chk entries for transition array
  926. X *
  927. X * synopsis
  928. X *   int state[numchars + 1], numchars, statenum, deflink, totaltrans;
  929. X *   mkentry( state, numchars, statenum, deflink, totaltrans );
  930. X *
  931. X * "state" is a transition array "numchars" characters in size, "statenum"
  932. X * is the offset to be used into the base/def tables, and "deflink" is the
  933. X * entry to put in the "def" table entry.  If "deflink" is equal to
  934. X * "JAMSTATE", then no attempt will be made to fit zero entries of "state"
  935. X * (i.e., jam entries) into the table.  It is assumed that by linking to
  936. X * "JAMSTATE" they will be taken care of.  In any case, entries in "state"
  937. X * marking transitions to "SAME_TRANS" are treated as though they will be
  938. X * taken care of by whereever "deflink" points.  "totaltrans" is the total
  939. X * number of transitions out of the state.  If it is below a certain threshold,
  940. X * the tables are searched for an interior spot that will accommodate the
  941. X * state array.
  942. X */
  943. X
  944. mkentry( state, numchars, statenum, deflink, totaltrans )
  945. register int *state;
  946. int numchars, statenum, deflink, totaltrans;
  947. X
  948. X    {
  949. X    register int minec, maxec, i, baseaddr;
  950. X    int tblbase, tbllast;
  951. X
  952. X    if ( totaltrans == 0 )
  953. X    { /* there are no out-transitions */
  954. X    if ( deflink == JAMSTATE )
  955. X        base[statenum] = JAMSTATE;
  956. X    else
  957. X        base[statenum] = 0;
  958. X
  959. X    def[statenum] = deflink;
  960. X    return;
  961. X    }
  962. X
  963. X    for ( minec = 1; minec <= numchars; ++minec )
  964. X    {
  965. X    if ( state[minec] != SAME_TRANS )
  966. X        if ( state[minec] != 0 || deflink != JAMSTATE )
  967. X        break;
  968. X    }
  969. X
  970. X    if ( totaltrans == 1 )
  971. X    {
  972. X    /* there's only one out-transition.  Save it for later to fill
  973. X     * in holes in the tables.
  974. X     */
  975. X    stack1( statenum, minec, state[minec], deflink );
  976. X    return;
  977. X    }
  978. X
  979. X    for ( maxec = numchars; maxec > 0; --maxec )
  980. X    {
  981. X    if ( state[maxec] != SAME_TRANS )
  982. X        if ( state[maxec] != 0 || deflink != JAMSTATE )
  983. X        break;
  984. X    }
  985. X
  986. X    /* Whether we try to fit the state table in the middle of the table
  987. X     * entries we have already generated, or if we just take the state
  988. X     * table at the end of the nxt/chk tables, we must make sure that we
  989. X     * have a valid base address (i.e., non-negative).  Note that not only are
  990. X     * negative base addresses dangerous at run-time (because indexing the
  991. X     * next array with one and a low-valued character might generate an
  992. X     * array-out-of-bounds error message), but at compile-time negative
  993. X     * base addresses denote TEMPLATES.
  994. X     */
  995. X
  996. X    /* find the first transition of state that we need to worry about. */
  997. X    if ( totaltrans * 100 <= numchars * INTERIOR_FIT_PERCENTAGE )
  998. X    { /* attempt to squeeze it into the middle of the tabls */
  999. X    baseaddr = firstfree;
  1000. X
  1001. X    while ( baseaddr < minec )
  1002. X        {
  1003. X        /* using baseaddr would result in a negative base address below
  1004. X         * find the next free slot
  1005. X         */
  1006. X        for ( ++baseaddr; chk[baseaddr] != 0; ++baseaddr )
  1007. X        ;
  1008. X        }
  1009. X
  1010. X    if ( baseaddr + maxec - minec >= current_max_xpairs )
  1011. X        expand_nxt_chk();
  1012. X
  1013. X    for ( i = minec; i <= maxec; ++i )
  1014. X        if ( state[i] != SAME_TRANS )
  1015. X        if ( state[i] != 0 || deflink != JAMSTATE )
  1016. X            if ( chk[baseaddr + i - minec] != 0 )
  1017. X            { /* baseaddr unsuitable - find another */
  1018. X            for ( ++baseaddr;
  1019. X                  baseaddr < current_max_xpairs &&
  1020. X                  chk[baseaddr] != 0;
  1021. X                  ++baseaddr )
  1022. X                ;
  1023. X
  1024. X            if ( baseaddr + maxec - minec >= current_max_xpairs )
  1025. X                expand_nxt_chk();
  1026. X
  1027. X            /* reset the loop counter so we'll start all
  1028. X             * over again next time it's incremented
  1029. X             */
  1030. X
  1031. X            i = minec - 1;
  1032. X            }
  1033. X    }
  1034. X
  1035. X    else
  1036. X    {
  1037. X    /* ensure that the base address we eventually generate is
  1038. X     * non-negative
  1039. X     */
  1040. X    baseaddr = max( tblend + 1, minec );
  1041. X    }
  1042. X
  1043. X    tblbase = baseaddr - minec;
  1044. X    tbllast = tblbase + maxec;
  1045. X
  1046. X    if ( tbllast >= current_max_xpairs )
  1047. X    expand_nxt_chk();
  1048. X
  1049. X    base[statenum] = tblbase;
  1050. X    def[statenum] = deflink;
  1051. X
  1052. X    for ( i = minec; i <= maxec; ++i )
  1053. X    if ( state[i] != SAME_TRANS )
  1054. X        if ( state[i] != 0 || deflink != JAMSTATE )
  1055. X        {
  1056. X        nxt[tblbase + i] = state[i];
  1057. X        chk[tblbase + i] = statenum;
  1058. X        }
  1059. X
  1060. X    if ( baseaddr == firstfree )
  1061. X    /* find next free slot in tables */
  1062. X    for ( ++firstfree; chk[firstfree] != 0; ++firstfree )
  1063. X        ;
  1064. X
  1065. X    tblend = max( tblend, tbllast );
  1066. X    }
  1067. X
  1068. X
  1069. X/* mk1tbl - create table entries for a state (or state fragment) which
  1070. X *            has only one out-transition
  1071. X *
  1072. X * synopsis
  1073. X *   int state, sym, onenxt, onedef;
  1074. X *   mk1tbl( state, sym, onenxt, onedef );
  1075. X */
  1076. X
  1077. mk1tbl( state, sym, onenxt, onedef )
  1078. int state, sym, onenxt, onedef;
  1079. X
  1080. X    {
  1081. X    if ( firstfree < sym )
  1082. X    firstfree = sym;
  1083. X
  1084. X    while ( chk[firstfree] != 0 )
  1085. X    if ( ++firstfree >= current_max_xpairs )
  1086. X        expand_nxt_chk();
  1087. X
  1088. X    base[state] = firstfree - sym;
  1089. X    def[state] = onedef;
  1090. X    chk[firstfree] = state;
  1091. X    nxt[firstfree] = onenxt;
  1092. X
  1093. X    if ( firstfree > tblend )
  1094. X    {
  1095. X    tblend = firstfree++;
  1096. X
  1097. X    if ( firstfree >= current_max_xpairs )
  1098. X        expand_nxt_chk();
  1099. X    }
  1100. X    }
  1101. X
  1102. X
  1103. X/* mkprot - create new proto entry
  1104. X *
  1105. X * synopsis
  1106. X *   int state[], statenum, comstate;
  1107. X *   mkprot( state, statenum, comstate );
  1108. X */
  1109. X
  1110. mkprot( state, statenum, comstate )
  1111. int state[], statenum, comstate;
  1112. X
  1113. X    {
  1114. X    int i, slot, tblbase;
  1115. X
  1116. X    if ( ++numprots >= MSP || numecs * numprots >= PROT_SAVE_SIZE )
  1117. X    {
  1118. X    /* gotta make room for the new proto by dropping last entry in
  1119. X     * the queue
  1120. X     */
  1121. X    slot = lastprot;
  1122. X    lastprot = protprev[lastprot];
  1123. X    protnext[lastprot] = NIL;
  1124. X    }
  1125. X
  1126. X    else
  1127. X    slot = numprots;
  1128. X
  1129. X    protnext[slot] = firstprot;
  1130. X
  1131. X    if ( firstprot != NIL )
  1132. X    protprev[firstprot] = slot;
  1133. X
  1134. X    firstprot = slot;
  1135. X    prottbl[slot] = statenum;
  1136. X    protcomst[slot] = comstate;
  1137. X
  1138. X    /* copy state into save area so it can be compared with rapidly */
  1139. X    tblbase = numecs * (slot - 1);
  1140. X
  1141. X    for ( i = 1; i <= numecs; ++i )
  1142. X    protsave[tblbase + i] = state[i];
  1143. X    }
  1144. X
  1145. X
  1146. X/* mktemplate - create a template entry based on a state, and connect the state
  1147. X *              to it
  1148. X *
  1149. X * synopsis
  1150. X *   int state[], statenum, comstate, totaltrans;
  1151. X *   mktemplate( state, statenum, comstate, totaltrans );
  1152. X */
  1153. X
  1154. mktemplate( state, statenum, comstate )
  1155. int state[], statenum, comstate;
  1156. X
  1157. X    {
  1158. X    int i, numdiff, tmpbase, tmp[CSIZE + 1];
  1159. X    char transset[CSIZE + 1];
  1160. X    int tsptr;
  1161. X
  1162. X    ++numtemps;
  1163. X
  1164. X    tsptr = 0;
  1165. X
  1166. X    /* calculate where we will temporarily store the transition table
  1167. X     * of the template in the tnxt[] array.  The final transition table
  1168. X     * gets created by cmptmps()
  1169. X     */
  1170. X
  1171. X    tmpbase = numtemps * numecs;
  1172. X
  1173. X    if ( tmpbase + numecs >= current_max_template_xpairs )
  1174. X    {
  1175. X    current_max_template_xpairs += MAX_TEMPLATE_XPAIRS_INCREMENT;
  1176. X
  1177. X    ++num_reallocs;
  1178. X
  1179. X    tnxt = reallocate_integer_array( tnxt, current_max_template_xpairs );
  1180. X    }
  1181. X
  1182. X    for ( i = 1; i <= numecs; ++i )
  1183. X    if ( state[i] == 0 )
  1184. X        tnxt[tmpbase + i] = 0;
  1185. X    else
  1186. X        {
  1187. X        transset[tsptr++] = i;
  1188. X        tnxt[tmpbase + i] = comstate;
  1189. X        }
  1190. X
  1191. X    if ( usemecs )
  1192. X    mkeccl( transset, tsptr, tecfwd, tecbck, numecs );
  1193. X
  1194. X    mkprot( tnxt + tmpbase, -numtemps, comstate );
  1195. X
  1196. X    /* we rely on the fact that mkprot adds things to the beginning
  1197. X     * of the proto queue
  1198. X     */
  1199. X
  1200. X    numdiff = tbldiff( state, firstprot, tmp );
  1201. X    mkentry( tmp, numecs, statenum, -numtemps, numdiff );
  1202. X    }
  1203. X
  1204. X
  1205. X/* mv2front - move proto queue element to front of queue
  1206. X *
  1207. X * synopsis
  1208. X *   int qelm;
  1209. X *   mv2front( qelm );
  1210. X */
  1211. X
  1212. mv2front( qelm )
  1213. int qelm;
  1214. X
  1215. X    {
  1216. X    if ( firstprot != qelm )
  1217. X    {
  1218. X    if ( qelm == lastprot )
  1219. X        lastprot = protprev[lastprot];
  1220. X
  1221. X    protnext[protprev[qelm]] = protnext[qelm];
  1222. X
  1223. X    if ( protnext[qelm] != NIL )
  1224. X        protprev[protnext[qelm]] = protprev[qelm];
  1225. X
  1226. X    protprev[qelm] = NIL;
  1227. X    protnext[qelm] = firstprot;
  1228. X    protprev[firstprot] = qelm;
  1229. X    firstprot = qelm;
  1230. X    }
  1231. X    }
  1232. X
  1233. X
  1234. X/* ntod - convert an ndfa to a dfa
  1235. X *
  1236. X * synopsis
  1237. X *    ntod();
  1238. X *
  1239. X *  creates the dfa corresponding to the ndfa we've constructed.  the
  1240. X *  dfa starts out in state #1.
  1241. X */
  1242. ntod()
  1243. X
  1244. X    {
  1245. X    int *accset, ds, nacc, newds;
  1246. X    int duplist[CSIZE + 1], sym, hashval, numstates, dsize;
  1247. X    int targfreq[CSIZE + 1], targstate[CSIZE + 1], state[CSIZE + 1];
  1248. X    int *nset, *dset;
  1249. X    int targptr, totaltrans, i, comstate, comfreq, targ;
  1250. X    int *epsclosure(), snstods(), symlist[CSIZE + 1];
  1251. X
  1252. X    /* this is so find_table_space(...) will know where to start looking in
  1253. X     * chk/nxt for unused records for space to put in the state
  1254. X     */
  1255. X    if ( fullspd )
  1256. X    firstfree = 0;
  1257. X
  1258. X    accset = allocate_integer_array( accnum + 1 );
  1259. X    nset = allocate_integer_array( current_max_dfa_size );
  1260. X
  1261. X    todo_head = todo_next = 0;
  1262. X
  1263. X#define ADD_QUEUE_ELEMENT(element) \
  1264. X    if ( ++element >= current_max_dfas ) \
  1265. X        { /* check for queue overflowing */ \
  1266. X        if ( todo_head == 0 ) \
  1267. X        increase_max_dfas(); \
  1268. X        else \
  1269. X        element = 0; \
  1270. X        }
  1271. X
  1272. X#define NEXT_QUEUE_ELEMENT(element) ((element + 1) % (current_max_dfas + 1))
  1273. X
  1274. X    for ( i = 0; i <= CSIZE; ++i )
  1275. X    {
  1276. X    duplist[i] = NIL;
  1277. X    symlist[i] = false;
  1278. X    }
  1279. X
  1280. X    for ( i = 0; i <= accnum; ++i )
  1281. X    accset[i] = NIL;
  1282. X
  1283. X    if ( trace )
  1284. X    {
  1285. X    dumpnfa( scset[1] );
  1286. X    fputs( "\n\nDFA Dump:\n\n", stderr );
  1287. X    }
  1288. X
  1289. X    inittbl();
  1290. X
  1291. X    if ( fullspd )
  1292. X    {
  1293. X    for ( i = 0; i <= numecs; ++i )
  1294. X        state[i] = 0;
  1295. X    place_state( state, 0, 0 );
  1296. X    }
  1297. X
  1298. X    if ( fulltbl )
  1299. X    {
  1300. X    /* declare it "short" because it's a real long-shot that that
  1301. X     * won't be large enough
  1302. X     */
  1303. X    printf( "static short int %c[][%d] =\n    {\n", NEXTARRAY,
  1304. X        numecs + 1 ); /* '}' so vi doesn't get too confused */
  1305. X
  1306. X    /* generate 0 entries for state #0 */
  1307. X    for ( i = 0; i <= numecs; ++i )
  1308. X        mk2data( 0 );
  1309. X
  1310. X    /* force ',' and dataflush() next call to mk2data */
  1311. X    datapos = NUMDATAITEMS;
  1312. X
  1313. X    /* force extra blank line next dataflush() */
  1314. X    dataline = NUMDATALINES;
  1315. X    }
  1316. X
  1317. X    /* create the first states */
  1318. X
  1319. X    for ( i = 1; i <= lastsc * 2; ++i )
  1320. X    {
  1321. X    numstates = 1;
  1322. X
  1323. X    /* for each start condition, make one state for the case when
  1324. X     * we're at the beginning of the line (the '%' operator) and
  1325. X     * one for the case when we're not
  1326. X     */
  1327. X    if ( i % 2 == 1 )
  1328. X        nset[numstates] = scset[(i / 2) + 1];
  1329. X    else
  1330. X        nset[numstates] = mkbranch( scbol[i / 2], scset[i / 2] );
  1331. X
  1332. X    nset = epsclosure( nset, &numstates, accset, &nacc, &hashval );
  1333. X
  1334. X    if ( snstods( nset, numstates, accset, nacc, hashval, &ds ) )
  1335. X        {
  1336. X        numas = numas + nacc;
  1337. X        totnst = totnst + numstates;
  1338. X
  1339. X        todo[todo_next] = ds;
  1340. X        ADD_QUEUE_ELEMENT(todo_next);
  1341. X        }
  1342. X    }
  1343. X
  1344. X    if ( fulltbl )
  1345. X    {
  1346. X    if ( ! snstods( nset, 0, accset, 0, 0, &end_of_buffer_state ) )
  1347. X        flexfatal( "could not create unique end-of-buffer state" );
  1348. X
  1349. X    numas += 1;
  1350. X
  1351. X    todo[todo_next] = end_of_buffer_state;
  1352. X    ADD_QUEUE_ELEMENT(todo_next);
  1353. X    }
  1354. X
  1355. X    while ( todo_head != todo_next )
  1356. X    {
  1357. X    targptr = 0;
  1358. X    totaltrans = 0;
  1359. X
  1360. X    for ( i = 1; i <= numecs; ++i )
  1361. X        state[i] = 0;
  1362. X
  1363. X    ds = todo[todo_head];
  1364. X    todo_head = NEXT_QUEUE_ELEMENT(todo_head);
  1365. X
  1366. X    dset = dss[ds];
  1367. X    dsize = dfasiz[ds];
  1368. X
  1369. X    if ( trace )
  1370. X        fprintf( stderr, "state # %d:\n", ds );
  1371. X
  1372. X    sympartition( dset, dsize, symlist, duplist );
  1373. X
  1374. X    for ( sym = 1; sym <= numecs; ++sym )
  1375. X        {
  1376. X        if ( symlist[sym] )
  1377. X        {
  1378. X        symlist[sym] = 0;
  1379. X
  1380. X        if ( duplist[sym] == NIL )
  1381. X            { /* symbol has unique out-transitions */
  1382. X            numstates = symfollowset( dset, dsize, sym, nset );
  1383. X            nset = epsclosure( nset, &numstates, accset,
  1384. X                       &nacc, &hashval );
  1385. X
  1386. X            if ( snstods( nset, numstates, accset,
  1387. X                  nacc, hashval, &newds ) )
  1388. X            {
  1389. X            totnst = totnst + numstates;
  1390. X            todo[todo_next] = newds;
  1391. X            ADD_QUEUE_ELEMENT(todo_next);
  1392. X            numas = numas + nacc;
  1393. X            }
  1394. X
  1395. X            state[sym] = newds;
  1396. X
  1397. X            if ( trace )
  1398. X            fprintf( stderr, "\t%d\t%d\n", sym, newds );
  1399. X
  1400. X            targfreq[++targptr] = 1;
  1401. X            targstate[targptr] = newds;
  1402. X            ++numuniq;
  1403. X            }
  1404. X
  1405. X        else
  1406. X            {
  1407. X            /* sym's equivalence class has the same transitions
  1408. X             * as duplist(sym)'s equivalence class
  1409. X             */
  1410. X            targ = state[duplist[sym]];
  1411. X            state[sym] = targ;
  1412. X
  1413. X            if ( trace )
  1414. X            fprintf( stderr, "\t%d\t%d\n", sym, targ );
  1415. X
  1416. X            /* update frequency count for destination state */
  1417. X
  1418. X            i = 0;
  1419. X            while ( targstate[++i] != targ )
  1420. X            ;
  1421. X
  1422. X            ++targfreq[i];
  1423. X            ++numdup;
  1424. X            }
  1425. X
  1426. X        ++totaltrans;
  1427. X        duplist[sym] = NIL;
  1428. X        }
  1429. X        }
  1430. X
  1431. X    numsnpairs = numsnpairs + totaltrans;
  1432. X
  1433. X    if ( caseins && ! useecs )
  1434. X        {
  1435. X        register int j;
  1436. X
  1437. X        for ( i = 'A', j = 'a'; i <= 'Z'; ++i, ++j )
  1438. X        state[i] = state[j];
  1439. X        }
  1440. X
  1441. X    if ( fulltbl )
  1442. X        {
  1443. X        /* supply array's 0-element */
  1444. X        if ( ds == end_of_buffer_state )
  1445. X        mk2data( 0 );
  1446. X        else
  1447. X        mk2data( end_of_buffer_state );
  1448. X
  1449. X        for ( i = 1; i <= numecs; ++i )
  1450. X        mk2data( state[i] );
  1451. X
  1452. X        /* force ',' and dataflush() next call to mk2data */
  1453. X        datapos = NUMDATAITEMS;
  1454. X
  1455. X        /* force extra blank line next dataflush() */
  1456. X        dataline = NUMDATALINES;
  1457. X        }
  1458. X
  1459. X        else if ( fullspd )
  1460. X        place_state( state, ds, totaltrans );
  1461. X
  1462. X    else
  1463. X        {
  1464. X        /* determine which destination state is the most common, and
  1465. X         * how many transitions to it there are
  1466. X         */
  1467. X
  1468. X        comfreq = 0;
  1469. X        comstate = 0;
  1470. X
  1471. X        for ( i = 1; i <= targptr; ++i )
  1472. X        if ( targfreq[i] > comfreq )
  1473. X            {
  1474. X            comfreq = targfreq[i];
  1475. X            comstate = targstate[i];
  1476. X            }
  1477. X
  1478. X        bldtbl( state, ds, totaltrans, comstate, comfreq );
  1479. X        }
  1480. X    }
  1481. X
  1482. X    if ( fulltbl )
  1483. X    dataend();
  1484. X
  1485. X    else
  1486. X    {
  1487. X    cmptmps();  /* create compressed template entries */
  1488. X
  1489. X    /* create tables for all the states with only one out-transition */
  1490. X    while ( onesp > 0 )
  1491. X        {
  1492. X        mk1tbl( onestate[onesp], onesym[onesp], onenext[onesp],
  1493. X            onedef[onesp] );
  1494. X        --onesp;
  1495. X        }
  1496. X
  1497. X    mkdeftbl();
  1498. X    }
  1499. X    
  1500. X    }
  1501. X
  1502. X
  1503. X/* place_state - place a state into full speed transition table
  1504. X *
  1505. X * synopsis
  1506. X *     int *state, statenum, transnum;
  1507. X *     place_state( state, statenum, transnum );
  1508. X *
  1509. X * State is the statenum'th state.  It is indexed by equivalence class and
  1510. X * gives the number of the state to enter for a given equivalence class.
  1511. X * Transnum is the number of out-transitions for the state.
  1512. X */
  1513. X
  1514. place_state( state, statenum, transnum )
  1515. int *state, statenum, transnum;
  1516. X
  1517. X    {
  1518. X    register int i;
  1519. X    register int *state_ptr;
  1520. X    int position = find_table_space( state, transnum );
  1521. X
  1522. X    /* base is the table of start positions */
  1523. X    base[statenum] = position;
  1524. X
  1525. X    /* put in action number marker; this non-zero number makes sure that
  1526. X     * find_table_space() knows that this position in chk/nxt is taken
  1527. X     * and should not be used for another accepting number in another state
  1528. X     */
  1529. X    chk[position - 1] = 1;
  1530. X
  1531. X    /* put in end-of-buffer marker; this is for the same purposes as above */
  1532. X    chk[position] = 1;
  1533. X
  1534. X    /* place the state into chk and nxt */
  1535. X    state_ptr = &state[1];
  1536. X
  1537. X    for ( i = 1; i <= numecs; ++i, ++state_ptr )
  1538. X    if ( *state_ptr != 0 )
  1539. X        {
  1540. X        chk[position + i] = i;
  1541. X        nxt[position + i] = *state_ptr;
  1542. X        }
  1543. X
  1544. X    if ( position + numecs > tblend )
  1545. X    tblend = position + numecs;
  1546. X    }
  1547. X
  1548. X
  1549. X/* stack1 - save states with only one out-transition to be processed later
  1550. X *
  1551. X * synopsis
  1552. X *   int statenum, sym, nextstate, deflink;
  1553. X *   stack1( statenum, sym, nextstate, deflink );
  1554. X *
  1555. X * if there's room for another state one the "one-transition" stack, the
  1556. X * state is pushed onto it, to be processed later by mk1tbl.  If there's
  1557. X * no room, we process the sucker right now.
  1558. X */
  1559. X
  1560. stack1( statenum, sym, nextstate, deflink )
  1561. int statenum, sym, nextstate, deflink;
  1562. X
  1563. X    {
  1564. X    if ( onesp >= ONE_STACK_SIZE )
  1565. X    mk1tbl( statenum, sym, nextstate, deflink );
  1566. X
  1567. X    else
  1568. X    {
  1569. X    ++onesp;
  1570. X    onestate[onesp] = statenum;
  1571. X    onesym[onesp] = sym;
  1572. X    onenext[onesp] = nextstate;
  1573. X    onedef[onesp] = deflink;
  1574. X    }
  1575. X    }
  1576. X
  1577. X
  1578. X/* tbldiff - compute differences between two state tables
  1579. X *
  1580. X * synopsis
  1581. X *   int state[], pr, ext[];
  1582. X *   int tbldiff, numdifferences;
  1583. X *   numdifferences = tbldiff( state, pr, ext )
  1584. X *
  1585. X * "state" is the state array which is to be extracted from the pr'th
  1586. X * proto.  "pr" is both the number of the proto we are extracting from
  1587. X * and an index into the save area where we can find the proto's complete
  1588. X * state table.  Each entry in "state" which differs from the corresponding
  1589. X * entry of "pr" will appear in "ext".
  1590. X * Entries which are the same in both "state" and "pr" will be marked
  1591. X * as transitions to "SAME_TRANS" in "ext".  The total number of differences
  1592. X * between "state" and "pr" is returned as function value.  Note that this
  1593. X * number is "numecs" minus the number of "SAME_TRANS" entries in "ext".
  1594. X */
  1595. X
  1596. int tbldiff( state, pr, ext )
  1597. int state[], pr, ext[];
  1598. X
  1599. X    {
  1600. X    register int i, *sp = state, *ep = ext, *protp;
  1601. X    register int numdiff = 0;
  1602. X
  1603. X    protp = &protsave[numecs * (pr - 1)];
  1604. X
  1605. X    for ( i = numecs; i > 0; --i )
  1606. X    {
  1607. X    if ( *++protp == *++sp )
  1608. X        *++ep = SAME_TRANS;
  1609. X    else
  1610. X        {
  1611. X        *++ep = *sp;
  1612. X        ++numdiff;
  1613. X        }
  1614. X    }
  1615. X
  1616. X    return ( numdiff );
  1617. X    }
  1618. END_OF_FILE
  1619. if test 39351 -ne `wc -c <'tblcmp.c'`; then
  1620.     echo shar: \"'tblcmp.c'\" unpacked with wrong size!
  1621. fi
  1622. # end of 'tblcmp.c'
  1623. fi
  1624. echo shar: End of archive 5 \(of 5\).
  1625. cp /dev/null ark5isdone
  1626. MISSING=""
  1627. for I in 1 2 3 4 5 ; do
  1628.     if test ! -f ark${I}isdone ; then
  1629.     MISSING="${MISSING} ${I}"
  1630.     fi
  1631. done
  1632. if test "${MISSING}" = "" ; then
  1633.     echo You have unpacked all 5 archives.
  1634.     rm -f ark[1-9]isdone
  1635. else
  1636.     echo You still need to unpack the following archives:
  1637.     echo "        " ${MISSING}
  1638. fi
  1639. ##  End of shell archive.
  1640. exit 0
  1641.